#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>


#define SIZE 256
#define ZERO '\0'
#define NUM 32
#define SEP " "

char* gArgv[NUM];


const char* GetUser()
{
  const char* p=getenv("USER");
  if(p==NULL)
    return "None";
  return p;
}

const char* GetHostName()
{
  const char* p=getenv("HOSTNAME");
  if(p==NULL)
    return "None";
  return p;
}

const char* GetCwd()
{
  const char* p=getenv("PWD");
  if(p==NULL)
    return "None";
  return p;
}

void GetCwd2(const char** p)
{
  //1.先指向最后一个字符
  (*p)+=strlen(*p)-1;
  //2.指向从后往前的第一个“/”
  while((**p)!='/') (*p)--;
}

void MakeCommandLine()
{
  const char* user=GetUser();
  const char* hostname=GetHostName();
  const char* cwd=GetCwd();

  GetCwd2(&cwd);
  printf("[%s@%s %s]> ",user,hostname,strlen(cwd)==1?"/":cwd+1);
}

int GetUserCommand(char commandline[],size_t size)
{
  char* s=fgets(commandline,size,stdin);
  if(s==NULL) return 1;
  commandline[strlen(commandline)-1]=ZERO;
  return strlen(commandline);
}

void SplitCommand(char commandline[])
{
  char* s=strtok(commandline,SEP);
  gArgv[0]=s;
  int i=1;
  while((gArgv[i++]=strtok(NULL,SEP)))
    ;
}

int exit_code=0;

void ExecuteCommand()
{
  pid_t id =fork();
  if(id<0)
    exit(-1);
  else if(id==0)
  {
    //child
    execvp(gArgv[0],gArgv);
    exit(3);
  }
  else 
  {
    //parent
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0)
    {
      //等待成功
      exit_code=WEXITSTATUS(status);
      if(exit_code!=0)
      {
        printf("%s:%s:%d\n",gArgv[0],strerror(exit_code),exit_code);
      }
    }
  }
}

const char* GetHome()
{
  const char* p=getenv("HOME");
  if(p==NULL)  return "None";
  return p;
}

char cwd[SIZE];

void Cd()
{
  const char* path=gArgv[1];
  if(path==NULL) path=GetHome();
  chdir(path);

  char tmp[SIZE];
  getcwd(tmp,sizeof(tmp));
  snprintf(cwd,sizeof(cwd),"PWD=%s",tmp);
  putenv(cwd);
}

int CheckBuildin()
{
  int ret=0;
  if(strcmp("cd",gArgv[0])==0)
  {
    ret=1;
    Cd();
  }
  else if(strcmp("echo",gArgv[0])==0 && strcmp("$?",gArgv[1])==0)
  {
    ret=1;
    printf("%d\n",exit_code);
    exit_code=0;
  }
  return ret;
}



int main()
{
  while(1)
  {

    //1.输出命令行
    MakeCommandLine();

    //2.获取用户命令字符串
    char commandline[SIZE];
    int n=GetUserCommand(commandline,sizeof(commandline));
    //if(n==0)  continue;

    //3.命令行字符串分割
    SplitCommand(commandline);

    //int j=0;
    //for(;gArgv[j];j++)
    //{
    //  printf("gArgv[%d]->%s\n",j,gArgv[j]);
    //}

    //4.判断是否是内建命令
    int ret=CheckBuildin();
    if(ret) continue;

    //5.执行命令
    ExecuteCommand();

  }
  

  return 0;
}



